package com.ruoyi.web.controller.business.goods.factory;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.business.base.JoLambdaQW;
import com.ruoyi.business.base.PageParam;
import com.ruoyi.business.goods.domain.JbCommodity;
import com.ruoyi.business.goods.domain.JbCommodityOfflinePrice;
import com.ruoyi.business.goods.domain.JbProduct;
import com.ruoyi.business.goods.domain.vo.JbCommodityVo;
import com.ruoyi.business.goods.service.JbCommodityService;
import com.ruoyi.business.goods.service.JbProductService;
import com.ruoyi.common.annotation.JoException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.web.controller.business.goods.vo.JbConversionVO;
import com.ruoyi.web.controller.business.statistics.factory.JbProductRecipeFactory;
import com.ruoyi.web.controller.system.factory.SysDataScopeFactory;
import com.ruoyi.web.controller.tool.JoCodeUtils;
import com.ruoyi.web.core.JoController;
import lombok.Getter;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

/**
 * 业务 商品 工厂类
 *
 * @author Jyl
 */
@Component
public class JbCommodityFactory extends JoController
{

    @Getter
    @Autowired
    private JbCommodityService service;
    @Autowired
    private JbCommodityOfflinePriceFactory jbCommodityOfflinePriceFactory;
    @Autowired
    private JbProductClassifyFactory jbProductClassifyFactory;
    @Autowired
    private JbProductService jbProductService;
    @Autowired
    private SysDataScopeFactory sysDataScopeFactory;
    @Autowired
    private JbProductRecipeFactory jbProductRecipeFactory;


    /**
     * @param page        分页对象
     * @param jbCommodity 商品对象
     * @return 分页结果
     */
    public IPage<JbCommodity> list(PageParam page, JbCommodity jbCommodity)
    {
        //根据部门销售渠道查询
        String channel = getUser().getDept().getChannel();
        if (StrUtil.isNotEmpty(jbCommodity.getChannelType()))
        {//根据前端传入销售渠道查询
            channel = jbCommodity.getChannelType();
        }
//        String ids = sysDataScopeFactory.fnStrDataScope("1");
        String ids = "";

        JoLambdaQW<JbCommodity> select = new JoLambdaQW<>();
        select.lambda().and(StringUtils.isNotEmpty(page.getKeyword()), e -> e
                        .like(JbCommodity::getCommodityName, page.getKeyword())
                        .or()
                        .like(JbCommodity::getCommodityCode, page.getKeyword())
                )//关键字
                .eq(ObjectUtil.isNotEmpty(jbCommodity.getClassifyId()), JbCommodity::getClassifyId,
                        jbCommodity.getClassifyId())//分类
                .like(ObjectUtil.isNotEmpty(channel), JbCommodity::getChannelType,
                        channel)//渠道分类
                .eq(StringUtils.isNotEmpty(jbCommodity.getCommodityType()), JbCommodity::getCommodityType,
                        jbCommodity.getCommodityType())//产品类型
                .eq(StringUtils.isNotEmpty(jbCommodity.getStatus()), JbCommodity::getStatus,
                        jbCommodity.getStatus())//是否启用
        ;

        //因ids等于空，此逻辑暂时弃用
        select.and("1002".equals(channel) && StrUtil.isNotBlank(ids), e -> e
                .apply("id  in (select commodity_id from jb_commodity_offline_price jcop where jcop" +
                       ".department_ids ='0')")
                .or()
                .apply(StrUtil.format("id in ( SELECT\n" +
                                      "	commodity_id \n" +
                                      "FROM\n" +
                                      "	jb_commodity_offline_price jcop \n" +
                                      "WHERE\n" +
                                      "	jcop.department_ids IS NOT NULL \n" +
                                      "	AND jcop.department_ids <> '' \n" +
                                      "	AND jcop.department_ids <> '0' \n" +
                                      "	AND jcop.department_ids REGEXP '{}' )", ids.replaceAll(",",
                        "|")))
        );

        IPage<JbCommodity> iPage = service.page(page.b(), select);
        return iPage;
    }

    /**
     * 获取商品详细信息
     */
    public JbCommodity getInfo(Long id)
    {
        return service.getById(id);
    }

    /**
     * 获取商品详细信息
     */
    public JbCommodity getInfo(Long id, String deptId)
    {
        JbCommodity jbCommodity = service.getById(id);
        jbCommodity.setOfflinePrices(jbCommodityOfflinePriceFactory.list(id, deptId));
        return jbCommodity;
    }

    /**
     * 删除产品相关
     *
     * @param ids 产品主键
     * @return 执行结果
     */
    public Boolean deleteProductRelated(List<Long> ids)
    {
        return service.update(new LambdaUpdateWrapper<JbCommodity>()
                .in(JbCommodity::getProductId, ids)
                .set(JbCommodity::getDelFlag, "1")
        );
    }

    /**
     * 更新关联产品信息
     */
    public void updateProduct(JbCommodity jbCommodity)
    {
        JbProduct jbProduct = jbProductService.getById(jbCommodity.getProductId());
        jbCommodity.setChannelType(jbProduct.getSalesChannel());
        jbCommodity.setProductName(jbProduct.getProductName());
    }

    /**
     * 获取商品详细信息
     */
    public Boolean updateProduct(JbProduct jbProduct)
    {
        return service.update(new LambdaUpdateWrapper<JbCommodity>()
                .set(JbCommodity::getProductName, jbProduct.getProductName())
                .set(JbCommodity::getChannelType, jbProduct.getSalesChannel())
                .eq(JbCommodity::getProductId, jbProduct.getId())
        );
    }

    @SneakyThrows
    @JoException(message = "商品编辑异常！")
    public boolean edit(JbCommodity jbCommodity)
    {
        isNotNullByName(jbCommodity.getCommodityCode(), jbCommodity.getId());
        updateProduct(jbCommodity);
        fnConversion(jbCommodity);
        if (!service.updateById(jbCommodity))
        {
            return false;
        }
        try
        {
            jbProductRecipeFactory.isGoodsAll();
        } catch (Exception e)
        {
            logger.error("编辑 商品同步配方库,{}", e.getMessage());
        }

        return jbCommodityOfflinePriceFactory.edits(jbCommodity.getOfflinePrices(), jbCommodity.getId());
    }

    /**
     * 检查是否有重名编码 商品
     *
     * @param code 外部编码
     * @param id   主键
     * @return 执行结果
     */
    public boolean isNotNullByName(String code, Long id)
    {
        //2025年2月27日16:21:13 吴经理 商品ID重复不能录入的判断放开
//        List<JbCommodity> list = service.list(new LambdaQueryWrapper<JbCommodity>()
//                .eq(JbCommodity::getCommodityCode, code)
//                .ne(ObjectUtil.isNotEmpty(id), JbCommodity::getId, id)
//        );
//        if (!list.isEmpty())
//        {
//            throw new ServiceException("已存在相同编码的商品");
//        }

        return true;
    }

    /**
     * 查询产品分类树
     */
    public JSONArray listClassify()
    {
        return jbProductClassifyFactory.listAll(JbProductClassifyFactory.COMMODIYTYPE);
    }

    /**
     * 查询商品名称和产品农药列表
     */
    public List<JbCommodityVo> listNameAll(JbCommodity jbCommodity)
    {
        return service.listNameAll(jbCommodity);
    }

    /**
     * 查询商品列表，根据登录人部门渠道类型
     *
     * @param page        分页
     * @param jbCommodity 商品
     * @return 分页结果
     */
    public IPage<JbCommodity> listType(PageParam page, JbCommodity jbCommodity)
    {
        //添加线上线下过滤
        jbCommodity.setChannelType(getLoginUser().getUser().getDept().getChannel());
        IPage<JbCommodity> page1 = list(page, jbCommodity);
        for (JbCommodity record : page1.getRecords())
        {
            if (StrUtil.contains(record.getChannelType(), "1002"))
            {
                record.setOfflinePrices(jbCommodityOfflinePriceFactory.list(record.getId(),
                        String.valueOf(getLoginUser().getDeptId())));
            }
        }
        return page1;
    }

    /**
     * 新增商品
     *
     * @param jbCommodity 商品对象
     * @return 执行解雇o
     */
    @JoException(message = "商品新增异常！")
    @Transactional
    public Boolean add(JbCommodity jbCommodity)
    {
        isNotNullByName(jbCommodity.getCommodityCode(), null);
        jbCommodity.setCommodityNumber(JoCodeUtils.CODE().COMMODITY);
        updateProduct(jbCommodity);
        fnConversion(jbCommodity);
        if (!service.save(jbCommodity))
        {
            return false;
        }

        jbCommodityOfflinePriceFactory.adds(
                jbCommodity.getOfflinePrices(),
                jbCommodity.getId()
        );
        try
        {
            jbProductRecipeFactory.isGoodsAll();
        } catch (Exception e)
        {
            logger.error("新增商品同步配方库,{}", e.getMessage());
        }

        return true;
    }

    /**
     * 计算 折算价格
     *
     * @param jbCommodity
     */
    public void fnConversion(JbCommodity jbCommodity)
    {
        Long caseQuantity = jbCommodity.getCaseQuantity();
        BigDecimal cassUnitPrice = jbCommodity.getCaseUnitPrice();
        BigDecimal unitContent = jbCommodity.getUnitContent();

        JbConversionVO jbConversionVO = new JbConversionVO();
        BeanUtils.copyProperties(jbCommodity, jbConversionVO);
        fnConversionImpl(jbConversionVO, caseQuantity, cassUnitPrice, unitContent);
        BeanUtils.copyProperties(jbConversionVO, jbCommodity);

        //折算 线下价格
        for (JbCommodityOfflinePrice offlinePrice : jbCommodity.getOfflinePrices())
        {
            jbConversionVO = new JbConversionVO();
            BeanUtils.copyProperties(offlinePrice, jbConversionVO);
            fnConversionImpl(jbConversionVO, caseQuantity, offlinePrice.getCustomPrice(), unitContent);
            BeanUtils.copyProperties(jbConversionVO, offlinePrice);
        }
    }

    /**
     * 逻辑 处理折算价格
     *
     * @param jbConversionVO 商品折算对象
     * @param caseQuantity   整件数量
     * @param cassUnitPrice  箱价
     * @param unitContent    单位含量
     */
    private void fnConversionImpl(JbConversionVO jbConversionVO, Long caseQuantity, BigDecimal cassUnitPrice,
                                  BigDecimal unitContent)
    {
        jbConversionVO.setBoxConversionUnitPrice(cassUnitPrice
                .divide(BigDecimal.valueOf(caseQuantity), 2, RoundingMode.HALF_UP));
        if (ObjectUtil.isEmpty(jbConversionVO.getTonPrice()))
        {
            jbConversionVO.setTonPrice(BigDecimal.ZERO);
            jbConversionVO.setTonConversionUnitPrice(BigDecimal.ZERO);
        } else
        {
            BigDecimal itemWeight = new BigDecimal("1000.00")
                    .divide(unitContent, 2, RoundingMode.HALF_UP);
            jbConversionVO.setTonConversionUnitPrice(jbConversionVO.getTonPrice()
                    .divide(itemWeight, 2, RoundingMode.HALF_UP));
        }
    }

    /**
     * 商品折算价格
     *
     * @param ids 主键集合
     * @return 数据集
     */
    public JSONArray conversion(Long[] ids)
    {
        List<JbCommodity> list = service.list(new LambdaQueryWrapper<JbCommodity>()
                .in(JbCommodity::getId, ids));
        JSONArray jsonArray = new JSONArray();

        for (JbCommodity jbCommodity : list)
        {
            JSONObject jsonObject = new JSONObject();
            if (getLoginUser().getUser().getDept().getChannel().equals("1002"))
            {//线下价格
                List<JbCommodityOfflinePrice> offlinePrices = jbCommodityOfflinePriceFactory.list(jbCommodity.getId(),
                        getLoginUser().getDeptId() + "");
                JbCommodityOfflinePrice jbCommodityOfflinePrice = offlinePrices.get(0);
                jsonObject.fluentPut("price", new JSONObject()
                        .fluentPut("unitPrice", jbCommodityOfflinePrice.getFactoryPrice())
                        .fluentPut("boxConversionUnitPrice", jbCommodityOfflinePrice.getBoxConversionUnitPrice())
                        .fluentPut("tonConversionUnitPrice", jbCommodityOfflinePrice.getTonConversionUnitPrice()));
            } else
            {//线上价格
                jsonObject.fluentPut("price", new JSONObject()
                        .fluentPut("unitPrice", jbCommodity.getOnlineUnitPrice())
                        .fluentPut("boxConversionUnitPrice", jbCommodity.getBoxConversionUnitPrice())
                        .fluentPut("tonConversionUnitPrice", jbCommodity.getTonConversionUnitPrice()));
            }

            //数量换算
            jsonObject.fluentPut("quantity", new JSONObject()
                    .fluentPut("toBox", jbCommodity.getCaseQuantity())
                    .fluentPut("toTon", BigDecimal.valueOf(jbCommodity.getCaseQuantity())
                                    .multiply(jbCommodity.getUnitContent())
                                    .divide(new BigDecimal(1000), 6, RoundingMode.HALF_UP)
                            //因为吨单位数量，大于单位含量kg 1000倍率，设前台计算小数位基准为6位
                    )
            );
            jsonArray.add(new JSONObject().fluentPut(jbCommodity.getId() + "", jsonObject));
        }
        return jsonArray;
    }
}
